/*
 * Shell.java
 *
 * Created on May 5, 2005, 8:05 AM
 *
 * To change this template, choose Tools | Options and locate the template under
 * the Source Creation and Management node. Right-click the template and choose
 * Open. You can then make changes to the template in the Source Editor.
 */

package com.milowski.monos.tools;

import java.io.*;
import java.util.logging.*;

import com.milowski.monos.scheme.*;
import kawa.*;
import kawa.standard.*;
import gnu.mapping.*;
import gnu.lists.*;
import gnu.expr.*;


/**
 *
 * @author R. Alexander Milowski
 */
public class Shell extends Procedure0or1
{
   
static String fineLog = 
"handlers= java.util.logging.ConsoleHandler\n"+
".level= FINE\n"+
"java.util.logging.ConsoleHandler.level = FINE\n"+
"java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter\n";
;
static String finerLog = 
"handlers= java.util.logging.ConsoleHandler\n"+
".level= FINER\n"+
"java.util.logging.ConsoleHandler.level = FINER\n"+
"java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter\n";
;
static String finestLog = 
"handlers= java.util.logging.ConsoleHandler\n"+
".level= FINEST\n"+
"java.util.logging.ConsoleHandler.level = FINEST\n"+
"java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter\n";
;
   public static void setLogLevel(Level level) {
      if (level==Level.FINE) {
         try {
            LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(fineLog.getBytes()));
         } catch (java.io.IOException ex) {
            ex.printStackTrace();
         }
      } else if (level==Level.FINER) {
         try {
            LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(finerLog.getBytes()));
         } catch (java.io.IOException ex) {
            ex.printStackTrace();
         }
      } else if (level==Level.FINEST) {
         try {
            LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(finestLog.getBytes()));
         } catch (java.io.IOException ex) {
            ex.printStackTrace();
         }
         
      }
   }
   static boolean initialized = false;

   Language language;
   /** Creates a new instance of Shell */
   public Shell(Language language)
   {
      this.language = language;
   }
   
   public Object apply0 ()
   {
      kawa.Shell.run(language, Environment.getCurrent());
      return Values.empty;
   }

   public Object apply1(Object env)
   {
      kawa.Shell.run(language, (Environment) env);
      return Values.empty;
   }

   public static void setArgs (String[] args, int arg_start)
   {
      int nargs = args.length - arg_start;
      Object[] array = new Object[nargs];
      for (int i = 0; i<nargs; i++) {
        array[i] = new FString (args[i + arg_start]);
      }
      FVector argVec = new FVector (array);
      Environment.getCurrent().put("command-line-arguments",argVec);
   }
   
   public static void init() 
      throws ClassNotFoundException,InstantiationException,IllegalAccessException
   {
      if (!initialized) {
         Scheme.registerEnvironment();
         Scheme scheme = Scheme.getInstance();
         //Language.getDefaultLanguage();

         init(scheme);
         initialized = true;
      }
      
   }
   
   public static void init(Scheme scheme) 
      throws ClassNotFoundException,InstantiationException,IllegalAccessException
   {
       Monos.init(scheme);
       Runnable syntaxModule = (Runnable)Class.forName("com.milowski.monos.scheme.syntax").newInstance();
       scheme.defineAll(syntaxModule);
   }
   
   public static Object eval(String sexp) 
      throws Throwable
   {
      return Scheme.getInstance().eval(sexp);
   }
   
   public static void run(String file) 
      throws Throwable
   {
      kawa.standard.load.apply(file, Environment.getCurrent(), false);
     
   }
   
   public static void main(String [] args) {
      int argidx = 0;

      try {
         init();
      } catch (Exception ex) {
         System.err.println("Cannot initialize monos environment due to: ");
         ex.printStackTrace();
         System.exit(1);
      }
      boolean done = false;
      while (!done && argidx<args.length && args[argidx].charAt(0)=='-') {
         if (args[argidx].equals("-f")) {
            argidx++;
            if (argidx==args.length) {
               System.err.println("The -f parameter requires a script filename.");
               System.exit(1);
            }
            setArgs(args,argidx+1);
            //System.err.println("Loading "+args[argidx]);
            try {
               run(args[argidx]);
            } catch (Throwable ex) {
               ex.printStackTrace();
            }
            System.out.flush();
            System.err.flush();
            done = true;
         } else if (args[argidx].equals("-l")) {
            argidx++;
            if (argidx==args.length) {
               System.err.println("The -l parameter requires an argument of 'fine', 'finer', or 'finest'.");
               System.exit(1);
            }
            if (args[argidx].equals("fine")) {
               setLogLevel(Level.FINE);
            } else if (args[argidx].equals("finer")) {
               setLogLevel(Level.FINER);
            } else if (args[argidx].equals("finest")) {
               setLogLevel(Level.FINEST);
            }
         } else if (args[argidx].equals("--load")) {
            argidx++;
            if (argidx==args.length) {
               System.err.println("The --load parameter requires a script filename.");
               System.exit(1);
            }
            kawa.Shell.runFile(args[argidx]);
         } else if (args[argidx].equals("-w")) {
            setArgs(args,argidx+1);
            try {
               new com.milowski.monos.scheme.ui.GuiConsole("Monos Shell",(Scheme)Language.getDefaultLanguage(),Environment.getCurrent());
            } catch (Exception ex) {
                System.err.println("failed to create monos window: "+ex);
                System.exit (-1);
             }
            done = true;
         }
         argidx++;
      }
      if (!done) {
         setArgs(args,argidx);
         kawa.Shell.run(Language.getDefaultLanguage(),Environment.getCurrent());
      }
   }
   
}
